import { fabric } from 'fabric';

interface GuideLine {
    p1: fabric.Point,
    p2: fabric.Point
}

function initGuidelines(canvas: fabric.Canvas) {
    let disabled = false;
    let prePoint: any = null;
    const ctx = canvas.getSelectionContext();
    const lineWidth = 1;
    const aligningLineColor = 'rgba(118,19,254)';
    let viewportTransform: number[] | undefined;
    let zoom = 1;

    function drawLine(x1: number, y1: number, x2: number, y2: number) {
        if (viewportTransform == null || disabled) return;
        ctx.save();
        ctx.setLineDash([3, 3]);
        ctx.lineWidth = lineWidth;
        ctx.strokeStyle = aligningLineColor;
        ctx.beginPath();
        ctx.moveTo(x1 * zoom + viewportTransform[4], y1 * zoom + viewportTransform[5]);
        ctx.lineTo(x2 * zoom + viewportTransform[4], y2 * zoom + viewportTransform[5]);
        ctx.stroke();
        ctx.restore();
    }

    const guideLines: GuideLine[] = [];

    canvas.on('mouse:down', () => {
        viewportTransform = canvas.viewportTransform;
        zoom = canvas.getZoom();
    });

    canvas.on('before:render', () => {
        // fix 保存图片时报错
        try {
            canvas.clearContext(canvas.contextTop);
        } catch (error) {
            console.log(error);
        }
    });

    canvas.on('mouse:move', (ev: fabric.IEvent<MouseEvent>) => {
        if (prePoint) {
            const absPoint = ev.absolutePointer || new fabric.Point(0, 0);

            const dx = absPoint.x - prePoint.x;
            const dy = absPoint.y - prePoint.y;

            if (dx !== 0) {
                const horizontalAngle = Math.abs(Math.atan(dy / dx)) * 180 / Math.PI;  // 弧度值
                // 小于5度
                if (horizontalAngle < 1) {
                    let x = 0;

                    if (dx > 0) {
                        x = 1000;
                    }
                    
                    const p2 = new fabric.Point(x, prePoint.y);
                    guideLines.push({
                        p1: prePoint,
                        p2
                    });
                } else if (horizontalAngle > 89) {
                    let y = 0;

                    if (dy > 0) {
                        y = 1000;
                    }
                    const p2 = new fabric.Point(prePoint.x, y);
                    guideLines.push({
                        p1: prePoint,
                        p2
                    });
                }
            }

        }
    });

    canvas.on('after:render', () => {
        for (let i = guideLines.length; i--; ) {
            const { p1, p2 } = guideLines[i];
            drawLine(p1.x, p1.y, p2.x, p2.y);
        }
        guideLines.length = 0;
    });

    canvas.on('mouse:up', () => {
        guideLines.length = 0;
        canvas.renderAll();
    });

    return {
        disable: () => (disabled = true),
        enable: () => (disabled = false),
        setPrePoint: (p: any) => (prePoint = p)
    };
}

export default initGuidelines;
